ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。
- web.xml配置
- ContextLoaderListener UML类图
- UML 时序图
- createWebApplicationContext
- loadParentContext
- configureAndRefreshWebApplicationContext
web.xml配置
通常在web.xml中如下配置:
1 | <context-param> |
ContextLoaderListener UML类图
ServletContext启动后会调用ServletContextListener的contextInitialized方法。
UML 时序图
"createWebApplicationContext
用指定的contextClass或者默认class实例化ConfigurableWebApplicationContext1
2
3
4
5
6
7
8
9//ContextLoader
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
Class<?> contextClass = determineContextClass(sc);
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
}
return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
}
寻找用来实例化ConfigurableWebApplicationContext的class(determineContextClass)
先寻找web.xml 中指定的contextClass,如果没有再使用ContextLoader.properties配置的默认实现类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23//ContextLoader.java
protected Class<?> determineContextClass(ServletContext servletContext) {
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);//contextClass
if (contextClassName != null) {
try {
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load custom context class [" + contextClassName + "]", ex);
}
}
else {
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
try {
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load default context class [" + contextClassName + "]", ex);
}
}
}
其中,在ContextLoader类中有这样的静态代码块:
1 | static { |
ContextLoader.properties文件如下,配置了WebApplicationContext接口的默认实现类
1 | # Default WebApplicationContext implementation class for ContextLoader. |
loadParentContext
日后分析
configureAndRefreshWebApplicationContext
主要功能是调用AbstractApplicationContext的refresh方法,加载bean1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// The application context id is still set to its original default value
// -> assign a more useful id based on available information
String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
if (idParam != null) {
wac.setId(idParam);
}
else {
// Generate default id...
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(sc.getContextPath()));
}
}
wac.setServletContext(sc);
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}
// The wac environment's #initPropertySources will be called in any case when the context
// is refreshed; do it eagerly here to ensure servlet property sources are in place for
// use in any post-processing or initialization that occurs below prior to #refresh
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
}
customizeContext(sc, wac);
wac.refresh();
}